package br.edu.catolica.sadbc.session;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.security.sasl.AuthenticationException;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.international.StatusMessage.Severity;
import org.jboss.seam.international.StatusMessages;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;

import br.edu.catolica.sadbc.core.util.Crypto;
import br.edu.catolica.sadbc.entity.Usuario;
import br.edu.catolica.sadbc.entity.enums.TipoUsuario;

@Name("authenticator")
public class Authenticator {
	
	private static final String UNKNOWN_AUTHENTICATION_ERROR = "Unknown authentication error";

	private static final String INVALID_USERNAME_PASSWORD = "Invalid username/password";

	private static final String SALT = "Sad@l1z3#2903";
	
	@Logger
	private Log log;

	@In
	Identity identity;
	
	@In
	Credentials credentials;
	
	@In
	EntityManager entityManager;

	public boolean authenticate() throws AuthenticationException {
		log.info("authenticating {0}", credentials.getUsername());
		// write your authentication logic here,
		// return true if the authentication was
		// successful, false otherwise

		if ("admin".equals(credentials.getUsername())) {
			identity.addRole("admin");
			return true;
		}
		try {
			Usuario usuario = null; 
			String senha = null;
			Query query = this.entityManager.createQuery("select u from Usuario u where lower(u.nomeUsuario) = lower(:nomeUsuario) and u.senha = :senha");
			query.setParameter("nomeUsuario", identity.getCredentials().getUsername());
			
			//FIXME - Lembrar de encryptar a senha
			senha = encrypt(identity.getCredentials().getPassword(), identity.getCredentials().getUsername());
			query.setParameter("senha", senha);
			
			usuario = (Usuario) query.getSingleResult();
			
			identity.addRole(TipoUsuario.getEnumDescription(usuario.getTipoUsuario()));
			
			Contexts.getSessionContext().set("usuarioSession", usuario);
			
			return true;
			
		} catch (NoResultException ex) {
			StatusMessages.instance().add(Severity.ERROR, INVALID_USERNAME_PASSWORD);
			throw new AuthenticationException(INVALID_USERNAME_PASSWORD);
		} catch (Exception ex) {
			StatusMessages.instance().add(Severity.ERROR, UNKNOWN_AUTHENTICATION_ERROR);
			throw new AuthenticationException(UNKNOWN_AUTHENTICATION_ERROR, ex);
		}
		
	}
	
	private String encrypt(String password, String sal) {
		return Crypto.instance().encoding(password, sal + SALT);
	}

}
